package com.db4o.odbgen.plugins.java.database;

import java.util.ArrayList;
import java.util.List;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;


import com.db4o.internal.odbgen.TemplatesUtils;
import com.db4o.internal.odbgen.plugins.TemplateList;
import com.db4o.internal.odbgen.plugins.java.database.UniqueXmlSchemaElement;
import com.db4o.odbgen.OdbgenException;
import com.db4o.odbgen.TargetLanguage;
import com.db4o.odbgen.plugins.MainGeneratorPlugin;
import com.db4o.odbgen.plugins.Plugin;
import com.db4o.odbgen.plugins.java.maingenerator.MainGenerator;
import com.db4o.odbgen.plugins.java.maingenerator.XmlSchemaUtils;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSClass;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSField;
import com.db4o.odbgen.plugins.java.maingenerator.typedxmlschema.TSMethod;


public class Unique implements Plugin{

	private MainGenerator _mainGenerator;

	/**
	 * 
	 * @author liviug
	 * Contains the list of standard templates used by {@link Unique}.
	 */
	private enum Templates implements TemplateList{
		UNIQUE(Templates.path, "unique.vm");
		private static final String path = "standardPlugins/java/database";

		
		private String _path;
		private String _name;

		Templates(String path, String name){
			this._path = path;
			this._name = name;
		}
		
		/**
		 * Returns the path and the name of the template.
		 */
		public String getQualifiedName() {
			return this._path+"/"+this._name;
		}
	}
	
	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public List<Class<? extends Plugin>> getPluginDependencies() {
		ArrayList<Class<? extends Plugin>> res = new ArrayList<Class<? extends Plugin>>();
		res.add(MainGenerator.class);
		return res;
	}

	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public void initialize(MainGeneratorPlugin mainGenerator) {
		this._mainGenerator = (MainGenerator)mainGenerator;
		
	}

	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public void start() throws OdbgenException {

		
		
		//Build a list of fields that have to be indexed.
		List<TSClass> classes = new ArrayList<TSClass>();
		List<TSField> uniqueFields = new ArrayList<TSField>();
		for(TSClass tsClass : this._mainGenerator.getTypedXmlSchema().getClasses()){
			for(TSField field : tsClass.getFields()){
				//The field must belong to XmlSchema.
				if(field.getElement()==null) continue;
				
				if(field.getElement().getBooleanChildValue(UniqueXmlSchemaElement.UNIQUE.getName())){
					classes.add(tsClass);
					uniqueFields.add(field);
				}
				
			}
		}
		
		//Build the content
		Template template = TemplatesUtils.getTemplateJar(Unique.Templates.UNIQUE.getQualifiedName(), this._mainGenerator.getStandardTemplatesJarName());
		VelocityContext context = new VelocityContext();
		context.put("classes", classes);
		context.put("uniqueFields", uniqueFields);
		String content = TemplatesUtils.merge(template, context);

		//Add the index to the methods used to configure the client and the server.
		TSMethod clientConfig = this._mainGenerator.getSchemaUtils().getApplyConfig(XmlSchemaUtils.Scenario.CLIENT);
		clientConfig.getContent().append(content);
		TSMethod serverConfig = this._mainGenerator.getSchemaUtils().getApplyConfig(XmlSchemaUtils.Scenario.SERVER);
		serverConfig.getContent().append(content);
		TSMethod embeddedConfig = this._mainGenerator.getSchemaUtils().getApplyConfig(XmlSchemaUtils.Scenario.EMBEDDED);
		embeddedConfig.getContent().append(content);
		
		//Add the proper import.
		this._mainGenerator.getSchemaUtils().getDb4oUtils().getImports().add("com.db4o.constraints.UniqueFieldValueConstraint");
		
	}


	/**
	 * See {@link Plugin} for details.
	 */
	@Override
	public boolean supportsTargetLanguage(TargetLanguage targetLanguage) {
		if(targetLanguage == TargetLanguage.JAVA){
			return true;
		}
		return false;
	}

}
